﻿#include "flutter_blue_help.h"
#include <flutter/encodable_value.h>
#include "flutter_blue_utils.h"
#include "flutter_blue_device_agent.h"
// 构造函数实现
FlutterBleHelp::FlutterBleHelp(SendMessageConnectorCall messageConnectorCall, LogToFlutterCall logToFlutterCall)
    : messageConnectorCall_(messageConnectorCall)
    , logToFlutterCall_(logToFlutterCall) {
    // 初始化其他成员变量
    event_paired_handler = std::make_unique<EventStreamHandler<>>();
}
//开始扫描配对设备
void FlutterBleHelp::StastartScanPairedDevices() {
    if (!deviceWatcher) {
        /// fetch paired devices
        // auto aqsFilter = L"System.Devices.Aep.ProtocolId:=\"{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}\" AND System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True";
        // auto aqsFilter = BluetoothDevice::GetDeviceSelectorFromPairingState(true) + L" AND System.Devices.Aep.IsConnected:=System.StructuredQueryType.Boolean#True";
        auto aqsFilter = BluetoothDevice::GetDeviceSelectorFromPairingState(true);
        auto requestedProperties = {
            // L"System.Devices.Aep.AepId",
            L"System.Devices.Aep.IsConnected",
            L"System.Devices.Aep.DeviceAddress"
            // L"System.Devices.Aep.Bluetooth.Le.IsConnectable",
            // L"System.Devices.Aep.Bluetooth.Cod.Major",
            // L"System.Devices.AepService.Bluetooth.ServiceGuid"
        };
        deviceWatcher = DeviceInformation::CreateWatcher(aqsFilter, requestedProperties, DeviceInformationKind::AssociationEndpoint);
        // TODO check if need, this => get_weak()
        deviceWatcherAddedToken = deviceWatcher.Added({ this, &FlutterBleHelp::DeviceWatcher_Added });
        deviceWatcherUpdatedToken = deviceWatcher.Updated({ this, &FlutterBleHelp::DeviceWatcher_Updated });
        deviceWatcherRemovedToken = deviceWatcher.Removed({ this, &FlutterBleHelp::DeviceWatcher_Removed });
        deviceWatcherEnumerationCompletedToken = deviceWatcher.EnumerationCompleted({ this, &FlutterBleHelp::DeviceWatcher_EnumerationCompleted });
        deviceWatcherStoppedToken = deviceWatcher.Stopped({ this, &FlutterBleHelp::DeviceWatcher_Stopped });
    }
    deviceWatcher.Start();
}
void FlutterBleHelp::StopScanPairedDevices() {
    if (deviceWatcher && IsDeviceWatcherStarted()) {
        //我们还没有清空deviceWatcher，因为我们想接收Stopped事件
        deviceWatcher.Stop();
    }
}

//蓝牙配对 新增
void FlutterBleHelp::DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation info) {
    // Since we have the collection databound to a UI element, we need to update the collection on the UI thread.
    // co_await resume_foreground(dispatcher);

    auto isConnected = lookupBooleanProperty(info, L"System.Devices.Aep.IsConnected");
    // auto aepId = lookupStringProperty(info, L"System.Devices.Aep.AepId");
    auto address = lookupStringProperty(info, L"System.Devices.Aep.DeviceAddress");

    logToFlutterCall_("DeviceWatcher_Added, isConnected=" + isConnected);
    // OutputDebugString((L"DeviceWatcher_Added " + winrt::to_hstring(aepId) + L"\n").c_str());

    // 守望者可能在我们等待逃跑的机会时停了下来。
    if (IsDeviceWatcherStarted()) {
        //auto st = info.Properties();
        event_paired_handler->Success(EncodableMap{
                {"status",      int64_t(sender.Status())},
                {"deviceId",    winrt::to_string(info.Id())},
                {"name",        winrt::to_string(info.Name())},
                {"isConnected", isConnected},
                {"address",     (int64_t)Utils::string_to_mac(winrt::to_string(address))}
            });
    }
}

//蓝牙配对更新
void FlutterBleHelp::DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate info) {
    // Watcher may have stopped while we were waiting for our chance to run.
    auto value = info.Properties().TryLookup(L"System.Devices.Aep.IsConnected");
    auto isConnected = value && unbox_value<bool>(value);
    logToFlutterCall_("DeviceWatcher_Updated, isConnected=" + isConnected);

    if (IsDeviceWatcherStarted()) {
        event_paired_handler->Success(
            EncodableMap{
                    {"status",      int64_t(sender.Status())},
                    {"deviceId",    winrt::to_string(info.Id())},
                    {"isConnected", isConnected}
            });
    }
}

// 蓝牙配对移除
void FlutterBleHelp::DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate info) {
    // Watcher may have stopped while we were waiting for our chance to run.
    auto value = info.Properties().TryLookup(L"System.Devices.Aep.IsConnected");
    auto isConnected = value && unbox_value<bool>(value);
    logToFlutterCall_("DeviceWatcher_Removed, isConnected=" + isConnected);

    if (IsDeviceWatcherStarted()) {
        event_paired_handler->Success(EncodableMap{
                {"status",      int64_t(sender.Status())},
                {"deviceId",    winrt::to_string(info.Id())},
                {"isConnected", isConnected}
            });
    }
}
//蓝牙配对已完成
void FlutterBleHelp::DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, IInspectable obj) {
    printf("DeviceWatcher_EnumerationCompleted\n");
    event_paired_handler->Success(EncodableMap{
            {"status", int64_t(sender.Status())}
        });
}
// 蓝牙配对结束
void FlutterBleHelp::DeviceWatcher_Stopped(DeviceWatcher sender, IInspectable obj) {
    printf("DeviceWatcher_Stopped\n");
    event_paired_handler->Success(EncodableMap{
            {"status", int64_t(sender.Status())}
        });
}


bool FlutterBleHelp::lookupBooleanProperty(DeviceInformation deviceInfo, param::hstring const& property) {
    auto value = deviceInfo.Properties().TryLookup(property);
    return value && unbox_value<bool>(value);
}

winrt::hstring FlutterBleHelp::lookupStringProperty(DeviceInformation deviceInfo, param::hstring const& property) {
    auto value = deviceInfo.Properties().TryLookup(property);
    return unbox_value<winrt::hstring>(value);
}

bool FlutterBleHelp::IsDeviceWatcherStarted() {
    if (deviceWatcher == nullptr) return false;

    DeviceWatcherStatus status = deviceWatcher.Status();
    return status == DeviceWatcherStatus::Started ||
        status == DeviceWatcherStatus::EnumerationCompleted;
}

bool FlutterBleHelp::IsDeviceWatcherRunning() {
    if (deviceWatcher == nullptr) return false;

    DeviceWatcherStatus status = deviceWatcher.Status();
    return status == DeviceWatcherStatus::Started ||
        status == DeviceWatcherStatus::EnumerationCompleted ||
        status == DeviceWatcherStatus::Stopping;
}